package com.firefightingiot.firefightingiot.web.service;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

/**
 * @Author: YangYu
 * @ClassName: AesGcm256Util
 * @Date: Created in 11:04 2022/8/15
 * @Description:
 */
public class AesGcm256Util {

    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    public static final int NONCE_BIT_SIZE = 128;
    public static final int MAC_BIT_SIZE = 128;
    public static final int KEY_BIT_SIZE = 256;
    private AesGcm256Util() {
    }
    /**
     * 创建密钥
     *
     * @return 密钥
     */
    public static byte[] key() {
        byte[] key = new byte[KEY_BIT_SIZE / 8];
        SECURE_RANDOM.nextBytes(key);
        return key;
    }
    /**
     * 创建向量
     *
     * @return 向量
     */
    public static byte[] iv() {
        byte[] iv = new byte[NONCE_BIT_SIZE / 8];
        SECURE_RANDOM.nextBytes(iv);
        return iv;
    }
    /**
     * 编码
     *
     * @param hexStr 文本
     * @return 字节数组
     */
    public static byte[] hexToByte(String hexStr) {
        int len = hexStr.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4)
                    + Character.digit(hexStr.charAt(i + 1), 16));
        }
        return data;
    }
    /**
     * 转为十六进制
     *
     * @param data 字节数组
     * @return 转换结果
     */
    public static String toHex(byte[] data) {
        StringBuilder ret = new StringBuilder();
        for (byte datum : data) {
            String hex = Integer.toHexString(datum & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret.append(hex.toUpperCase());
        }
        return ret.toString();
    }
    /**
     * 加密
     *
     * @param plainText 明文文本
     * @param key 密钥
     * @param iv 向量
     * @return 加密字符串
     */
    public static String encrypt(String plainText, byte[] key, byte[] iv) {
        String sr;
        try {
            byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
            GCMBlockCipher cipher = new GCMBlockCipher(new
                    AESFastEngine());
            AEADParameters parameters =
                    new AEADParameters(new KeyParameter(key),
                            MAC_BIT_SIZE, iv, null);
            cipher.init(true, parameters);
            byte[] encryptedBytes = new
                    byte[cipher.getOutputSize(plainBytes.length)];
            int retLen = cipher.processBytes(plainBytes, 0, plainBytes.length,
                    encryptedBytes, 0);
            cipher.doFinal(encryptedBytes, retLen);
            sr = Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage());
        }
        return sr;
    }
    /**
     * 解密
     *
     * @param encryptedText 已加密文本
     * @param key 密钥
     * @param iv 向量
     * @return 已解密文本
     */
    public static String decrypt(String encryptedText, byte[] key, byte[] iv) {
        String sr;
        try {
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
            GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
            AEADParameters parameters = new AEADParameters(new KeyParameter(key), MAC_BIT_SIZE, iv, null);
            cipher.init(false, parameters);
            byte[] plainBytes = new
                    byte[cipher.getOutputSize(encryptedBytes.length)];
            int retLen = cipher.processBytes
                    (encryptedBytes, 0, encryptedBytes.length, plainBytes, 0);
            cipher.doFinal(plainBytes, retLen);
            sr = new String(plainBytes, StandardCharsets.UTF_8);
        } catch (IllegalArgumentException | IllegalStateException |
                DataLengthException | InvalidCipherTextException ex) {
            throw new RuntimeException(ex.getMessage());
        }
        return sr;
    }

    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id","bfcc9012-3e1e-440f-9e6c-e9d6b5cc5e66");
        jsonObject.put("companyCode","370770101");
        jsonObject.put("hazardCode","370770101001");
        jsonObject.put("riskUnitName","反应器");
        jsonObject.put("hazardDep","分离加氢部");
        jsonObject.put("hazardLiablePerson","张三");
        jsonObject.put("deleted","0");
        jsonObject.put("createDate","2022-10-08 16:32:56");
        jsonObject.put("createBy","管理员");
        jsonObject.put("updateDate","2022-10-08 16:32:56");
        jsonObject.put("updateBy","杨");
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(jsonObject);
        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.put("data",jsonArray);
        System.out.println(jsonObject1.toJSONString(0));
        String encryptedStr = AesGcm256Util.encrypt(jsonObject1.toJSONString(0),
                AesGcm256Util.hexToByte("84702E415A73CE27077B5F726E7BDBB0"),
                AesGcm256Util.hexToByte("1C7AA98593AA69F4AAE119BD5C01D9ED"));
        System.out.println(encryptedStr);

        ///--------------------解密------------------------------------------
//        String resultStr = AesGcm256Util.decrypt("p5lS005LBfwN+fenMYjlBGOLGfS0cGgMYrxvfFddYR9e2gM2d8t35LS20i1lgjKmnGGALYjcJ5Ce0m9f2kAbEDbsNDIavtW6WX/wlS/wRlTcmEHCRaWVmrNY7U8TuYvkpUqgTE3j0AsqnbO5FwUg7FTHUZGwWsB+A4tszNee6pqSqq/VF92SED3dVO8jayPsAr6TH+NJZzU+j5x9Giqpqcp8chjjLpOivNxIWpxJQ4PC5bRvXA7NS50oO3+IZw+Iyq8UP9bXZLZrD+m1CrmQH5jUGiifvRdaMSs2TBOlBIjDmRPpx9CwyTb+aAWu+UJjQ0cPgT5BlzS/2Felh70Sf0qzjB3iki3Bo/qQfBCt85MPB0hBuwnw3CroYLfH+S0nYUc30rYvxAoQHlPSDEDNBENWG9iCIiPC8Pnmc4k0ex+9eKeYmot+UR/ZOo1Fxqyp3EeRNwqqbxLIN5ZUCcjC6gfHGhunDrtwIfx75KdCAQaVnRDEB7N/icCLUVOjaDBQRw==",
//                AesGcm256Util.hexToByte("84702E415A73CE27077B5F726E7BDBB0"),
//                AesGcm256Util.hexToByte("1C7AA98593AA69F4AAE119BD5C01D9ED"));
//        System.out.println(resultStr);
        Date date = new Date();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss:sss");
        System.out.println(dateFormat.format(date));
    }
}
